package kgame5.k3d.util3d.reslib {
import flash.system.ApplicationDomain;
import flash.system.LoaderContext;
import flash.display.LoaderInfo;

import kgame5.k3d.core.obj3d.info.material.MaterialInfo;
import kgame5.k3d.core.obj3d.node3d.animator.Animator3D;
import kgame5.k3d.core.parser.MD2Parser;
import kgame5.k3d.util3d.loader3d.Loader3DSkin;
import kgame5.kutil.KEvent;
import kgame5.kutil.T;

import flash.display.BitmapData;
import flash.display.Loader;
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.net.URLLoader;
import flash.net.URLLoaderDataFormat;
import flash.net.URLRequest;
import flash.utils.ByteArray;
import flash.utils.Dictionary;

/**
 * @author kk
 * 各种类型的资源都在这里,这个会自动加载，提取的时候用名字提取
 * md2 mtab skin
 * 
 * TODO 注意这个要改好，改成使用as3ds.Set的，保证没有重复的
 * TODO 改装成LoaderItem结构的
 * 
 * 资源仓库
 * 这个的用途是加载资源并提取资源
 * 
 * 具备去除重复资源的能力
 */
public class AssetLoaderX extends EventDispatcher {
	//事件
	public static const 
		EVENT_ALL_OK : String = "EVENT_ALL_OK",//资源全部加载完毕
		EVENT_ONE_OK : String = "EVENT_ONE_OK";//资源加载一个完毕

	private  var dict : Dictionary;//dict[fileUrl]=res
	private  var idx : int;
	//要加载的obj的文件地址,不能同时启动加载，否则解析的时候会堵塞，屏幕变卡
	private  var aFileUrl : Array;

	private var l_skin : Loader3DSkin;
	private var l_x : URLLoader;//直接用途是加载xml用的,也可以加载txt
	private var l_md2 : URLLoader;

	//用这个排除重复的
	//addUrl时用这个，load的时候用这个来生成aFileUrl
	private var dict_todo : Dictionary;

	private var tip : String = "";//加载的是何种东西，用于在Loading的时候显示“加载装扮等”

	public function AssetLoaderX(tip : String) {
		this.tip = tip;
		clear();
	}

	public function getTip() : String {
		return tip;
	}

	public function addUrl(sFileUrl : String) : void {
		trace2("addUrl", sFileUrl);
		//		if(sFileUrl!=null){
		//			aFileUrl.push(sFileUrl);
		//		}
		dict_todo[sFileUrl] = "";//用来排除重复的
	}

	public function load() : void {
		trace2("Lib3D.Start启动加载模型");
		
		//生成aFileUrl
		for(var s:String in dict_todo) {
			aFileUrl.push(s);
			trace2("加载资源", s);
		}
		
		idx = 0;
		
		//下一步
		loadNext();
	}

	public function clear() : void {
		dict = new Dictionary();
		aFileUrl = new Array();
		idx = 0;
		dict_todo = new Dictionary();
	}

	//skin
	private function loadSkin(sSkinUrl : String) : void {
		trace2("Lib3D.loadSkin", sSkinUrl);
		l_skin = new Loader3DSkin();
		l_skin.addEventListener(Loader3DSkin.EVENTTYPE_LOADOK, onLoadSkinOK);
		l_skin.Load(sSkinUrl);
	}

	private function onLoadSkinOK(e : KEvent) : void {
		trace2("Lib3D--.onLoadSkinOK", aFileUrl[idx]);
		//trace2("加载皮肤到了，全替换皮肤");
		var bmd : BitmapData = e.info.bmd;
		
		var sFileUrl : String = aFileUrl[idx];
		dict[sFileUrl] = bmd;
		
		//下一步
		onLoadItemOK();
	}

	//==加载某种未知的文件
	private  function loadX(sFileUrl : String) : void {
		trace2(this, "loadX", sFileUrl);
		l_x = new URLLoader();
		l_x.addEventListener(Event.COMPLETE, onLoadXOK);
		l_x.load(new URLRequest(sFileUrl));
	}

	private  function onLoadXOK(e : Event) : void {
		trace2(this, "onLoadXOK", aFileUrl[idx]);
		
		var sFileUrl : String = aFileUrl[idx];
		
		dict[sFileUrl] = l_x.data;
		
		//下一步
		onLoadItemOK();
	}

	//加载md2文件
	private  function loadMD2(sFileUrl : String) : void {
		trace2(this, "loadMD2", sFileUrl);
		l_md2 = new URLLoader();
		l_md2.addEventListener(Event.COMPLETE, onLoadMD2OK);
		l_md2.dataFormat = URLLoaderDataFormat.BINARY;
		l_md2.load(new URLRequest(sFileUrl));
	}

	private  function onLoadMD2OK(e : Event) : void {
		trace2(this, "onLoadMD2OK", aFileUrl[idx]);
		
		var sFileUrl : String = aFileUrl[idx];
		
		dict[sFileUrl] = l_md2.data;
		
		//下一步
		onLoadItemOK();
	}

	//加载swf文件
	private  function loadSWF(sFileUrl : String) : void {
		trace2(this, "loadMD2", sFileUrl);
		var l : Loader = new Loader();
		l.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoadSWFOK);
		
		l.load(new URLRequest(sFileUrl), new LoaderContext(false, ApplicationDomain.currentDomain));
	}

	private  function onLoadSWFOK(e : Event) : void {
		trace2(this, "onLoadSWFOK", aFileUrl[idx]);
		var l : LoaderInfo = e.currentTarget as LoaderInfo;
		var sFileUrl : String = aFileUrl[idx];
		
		dict[sFileUrl] = l.content;
		
		//下一步
		onLoadItemOK();
	}

	//加载下一个
	//注意，如果有.md2?223则(\.png)$ 是要失效的！
	private function loadNext() : void {
		trace2(this, "loadNext");
		
		var sFileUrl : String = aFileUrl[idx];
			
		var re_png : RegExp = /(\.png)/i;
		var re_jpg : RegExp = /(\.jpg)/i;
		var re_md2 : RegExp = /(\.md2)/i;
		var re_swf : RegExp = /(\.swf)/i;

		if(re_jpg.test(sFileUrl) || re_png.test(sFileUrl)) {
			//是jpg或png文件
			loadSkin(sFileUrl);
		}else if(re_md2.test(sFileUrl)) {
			//是md2文件
			loadMD2(sFileUrl);
		}else if(re_swf.test(sFileUrl)) {
			//是swf
			loadSWF(sFileUrl);
		} else {
			//未知类型文件
			loadX(sFileUrl);
		}
	}

	private function onLoadItemOK() : void {
		
		this.dispatchEvent(new KEvent(EVENT_ONE_OK));
		
		if(idx == aFileUrl.length - 1) {
			//通知加载完毕
			this.dispatchEvent(new KEvent(EVENT_ALL_OK));
		} else {
			//还没加载完
			idx++;
			loadNext();
		}
	}

	//返回加载进度0~100
	public function getProgress100() : int {
		if(aFileUrl == null || aFileUrl.length == 0) {
			return 0;
		} else {
			return (idx + 1) / aFileUrl.length * 100;
		}
	}

	//根据名字取出内容
	//* 1,var map_xml:XML=new XML(_lib3D_mapData.getData(NameX.getMapDataUrl(mapID)));
	//*  这个曾经花了很多时间做，原因是直接去的的这个不是xml，他只是个string,需要装换成xml
	public function getData(sName : String) : Object {
		return dict[sName];
	}

	//!!严重注意，这个是clone后的data
	public function getDataClone(sName : String) : Object {
		var dd : Object = getData(sName);
		var ba : ByteArray = new ByteArray();
		ba.writeObject(dd);
		ba.position = 0;
		return ba.readObject();
	}

	//取得一个Animator3D对象
	public function getAnimator3D(md2FileUrl : String,mtabFileUrl : String,skinFileUrl : String) : Animator3D {
		var anim : Animator3D = null;
		
		//md2
		var md2Parser : MD2Parser = new MD2Parser(4);//注意这里的fps是无效的，就是随便写的一个
		md2Parser.parse(getDataClone(md2FileUrl) as ByteArray);
		anim = md2Parser.animator;
		
		//mtab
		if(getData(mtabFileUrl) == null) {
			anim.setupActionTableXML(null);
		} else {
			anim.setupActionTableXML(new XML(getData(mtabFileUrl) as String));
		}
		
		//skin
		var mi : MaterialInfo = new MaterialInfo();
		mi.bmd = (getData(skinFileUrl) as BitmapData).clone();
		anim.setMaterialInfo(mi);
		
		return anim;
	}

	///////////////////调试信息//////////////////
	private function trace2(...args) : void {
		//T.p(args);
	}
}//end of class
}
